#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netdb.h>

#define GATE_PORT "36600"
#define MAX_PENDING_CONNECTIONS SOMAXCONN


FILE *fp = NULL;  //the log file
int seg_cnt = 0;
char seg[1024]="\0";
int g_ret;
int loginfo(char *pstr)
{
	time_t lt;
	char *ptm ;
	char buf[1024];
	int i, cnt= 0;
	struct tm *p;
	lt = time(NULL);
	p = localtime(&lt);
	ptm = ctime(&lt);
	
	char hostname[1024]="";

	gethostname(hostname, 1024);

	sprintf(buf, "[%s]%d-%d-%d %d:%d:%d %s\n", hostname, 1900+p->tm_year, 1 + p->tm_mon, p->tm_mday,  p->tm_hour, p->tm_min, p->tm_sec, pstr);
	
	for ( i = 0; buf[i] != '\0'; i++ ) 
	{
		cnt++;
	}
	fwrite(buf,cnt, 1, fp);	
	i = fflush(fp);
	return 0;
}

int gate()
{

	int listen_socket, work_socket, recv_len;
	int mail_socket, remote_addr_len;
	struct addrinfo hints, *res;
	struct sockaddr_storage remote_addr;
	char recvBuf[1024];
	char logbuf[1024];
	int ret, i,size;
	pid_t pid;
	int min_cnt, max_cnt, time_interval;
	char path[1024], para[1024], filename[1024];
	FILE* psegment;
	int open_ret, bytes_written;
	struct sockaddr_in clientAddr;
	memset(recvBuf, 0, sizeof(recvBuf));
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	
	getaddrinfo(NULL,GATE_PORT,&hints,&res);

	/* Initiate the listening socket */
	if ((listen_socket = socket(res->ai_family,
				    res->ai_socktype,
		       		    res->ai_protocol)) == -1)
	{
		   loginfo("Failed to create a listening socket.");
		   return 1;
	}

	/* Bind us to port GATE_PORT */
	if (bind(listen_socket,
		   res->ai_addr,
		   res->ai_addrlen) == -1)
	{
		   sprintf(logbuf, "Failed bind to %s.errno = %d",GATE_PORT, errno);
		   loginfo(logbuf);
		   return 1;
	}

	/* Set up listening */
	if (listen(listen_socket, MAX_PENDING_CONNECTIONS) == -1)
	{
		   loginfo("Failed to set up listening.");
		   return 1;
	}
	signal(SIGCHLD,SIG_IGN);  
	remote_addr_len = sizeof(clientAddr);
	loginfo("before accept");
	while ((work_socket = accept( listen_socket,
 				      (struct sockaddr*)&clientAddr,
					&remote_addr_len)) != -1)
	{
		   size = 0;
		   //sprintf(logbuf,"Received packet from %s:%d", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
        	   //loginfo(logbuf);
		   /* First recv parameters from segment. */
		   read(work_socket, para, 1024);
		   sprintf(logbuf, "para are %s", para);
		   loginfo(logbuf);
		   min_cnt = (int)(para[0]-'0');
		   max_cnt = (int)(para[1]-'0');
		   time_interval = (int)(para[2]-'0');
		   sprintf(logbuf, "parameters are %d, %d, %d\n", min_cnt, max_cnt, time_interval);
		   loginfo(logbuf);
		   /* Second save segment to a local file. */
		   sprintf(filename, "wzh000_segment%d", seg_cnt);
		   sprintf(seg, "/tmp/wzh000/wzh000_segment%d", seg_cnt);
		   open_ret = open(seg, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
		   if ( -1 == open_ret )
		   {
			sprintf(logbuf, "open err : %d", errno);
			loginfo(logbuf);
			continue;
		   }
		   while ((recv_len = read(work_socket, recvBuf, 1024)) > 0)
		   {
			bytes_written =  write( open_ret, recvBuf, recv_len);
			size += bytes_written;
			sprintf(logbuf, "bytes_written = %d", bytes_written);
			loginfo(logbuf);
		   }
		   sprintf(logbuf, "received data: %6d bytes", size);
		   loginfo(logbuf);
		   close(open_ret);
		   chmod(seg, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
		   pid=fork();
		   sprintf(logbuf, "pid = %d", pid);
		   loginfo(logbuf);
		   if ( 0 > pid)
		   {
				loginfo("fork error segment");
				continue;
		   }
		   if ( 0 == pid )
		   {
			seg_cnt++;
			sprintf(logbuf, "seg is %s, filename is %s", seg, filename);
			loginfo(logbuf);
	       	   	g_ret = execl(seg, filename, "2", "4", "1", NULL);
	           }
		   sprintf(logbuf, "g_ret is %d", g_ret);
		   loginfo(logbuf);	
		   close(work_socket);
		   
	}
	sprintf(logbuf, "socket = %d, errno = %d", work_socket, errno);
	loginfo(logbuf);
	close(listen_socket);
	return 0;
}


int main(int argc, char **argv )
{
	/* Our process ID and Session ID */
        pid_t pid, sid;
	int ret;         
	if (access("/tmp/wzh000",0) == -1)
	{
		ret = mkdir("/tmp/wzh000", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        	if( ret == -1)
        	{
			printf("mkdir err");
			exit (EXIT_FAILURE);
        	}
	}
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
		printf("fork failed! pid = %d\n", pid);
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then
           we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }

        /* Change the file mode mask */
        umask(0);
                
        /* Open any logs here */
	remove("/tmp/wzh000/gate.log");       
        fp = fopen( "/tmp/wzh000/gate.log", "a+");

	if ( NULL == fp)
	{
		printf("fopen err. errno=%d\n", errno);
		exit (EXIT_FAILURE);
	}       
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                /* Log the failure */
		printf("setsid failed. sid = %d\n", sid);
                exit(EXIT_FAILURE);
        }
        

        
        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                /* Log the failure */
		printf("chdir failed\n");
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
        gate();
        /* The Big Loop */
	fclose(fp);
   	exit(EXIT_SUCCESS);
}

	
